import { expect } from 'chai';
import { ethers } from 'ethers';
import bitcoreLib from 'bitcore-lib';
import bitcoreLibCash from 'bitcore-lib-cash';
import bitcoreLibDoge from 'bitcore-lib-doge';
import bitcoreLibLtc from 'bitcore-lib-ltc';
import { Transactions } from '../src';

describe('Transaction', function() {
  describe('create', () => {
    it('should create a BTC tx', () => {
      const recipients = [{ address: 'mpNpzMoprLnSBu8CWDunNCYeJq3Mzdk59V', amount: 1e8 }];
      const change = 'msnAsQcCdtzDyiSWb4ZnNxFwUy3P9ogQvY';
      const utxos = [
        {
          mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
          mintIndex: 1,
          value: 0.02503422 * 1e8,
          script: '76a91457884dcfe2ab46d3354a42d97333c95e5b80cf0188ac',
          address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5',
          sequenceNumber: 4294967294
        },
        {
          mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
          mintIndex: 0,
          value: 1e8,
          script: '76a9144e744a19a009a9dd43a23a7c12045c83e82ac9d288ac',
          address: 'mnfnJx2xWWptYmBzck3rdE851Dtu9GaZ3F',
          sequenceNumber: 4294967294
        }
      ];
      const fee = 7440;
      const tx = Transactions.create({ chain: 'BTC', recipients, change, utxos, fee, rbf: true });

      const keys = [
        {
          address: 'mnfnJx2xWWptYmBzck3rdE851Dtu9GaZ3F',
          privKey: 'cSFjiifSbZ2hU4jTFwE993LCe2rkZGULCTGWTDWXzHvuXRKxpnc1'
        },
        { address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5', privKey: 'cUWVirwp5vh1D6WWbYci3tuGniyf28ERpgU4uL5VSiFDfvNEhJqy' }
      ];
      const signed = Transactions.sign({ chain: 'BTC', tx, keys, utxos });
      const expected =
        '0200000002ab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e64010000006a47304402202eeb967801c0aad4f8241d8f90e2a9e2236f95c189165ba6b2ba4dc6b17bacbe02201b5d4dc0c32f6aa134d93698f85bf4c098d15fcbaada0b6ca2b8076fd8aa2741012102c8f8fa438666cbd287e28fb384b99555e4acce610e8141e887c9c458bba5db5cffffffffab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e64000000006a473044022072bdde2c0b413fc42d15d93e768a26f818dc5b225b9359235c09fd0452d6121a022007c00afa396d60d5b7919f2ba31e638817561cab4e2afed7a86dd636ee293c1001210321f2f13aed42db7257b64f77d574071a6e81e460ab3693eefb7482c12d1ff697ffffffff0200e1f505000000001976a914612fb4d5e27a28f5c54018d8948ca3a650741c4188acee152600000000001976a91486823ef7c8e210184cc8675189d37c4c9d8e1e0288ac00000000';
      expect(signed).to.eq(expected);
    });

    it('should sign a BTC opreturn tx', () => {
      const tx =
        '0200000001ab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e640100000000ffffffff0200000000000000000b6a096a07696f6e3a61626340420f00000000001976a91457884dcfe2ab46d3354a42d97333c95e5b80cf0188ac00000000';
      const utxos = [
        {
          mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
          mintIndex: 1,
          value: 0.02503422 * 1e8,
          script: '76a91457884dcfe2ab46d3354a42d97333c95e5b80cf0188ac',
          address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5',
          sequenceNumber: 4294967294
        }
      ];
      const keys = [
        {
          address: 'mnfnJx2xWWptYmBzck3rdE851Dtu9GaZ3F',
          privKey: 'cSFjiifSbZ2hU4jTFwE993LCe2rkZGULCTGWTDWXzHvuXRKxpnc1'
        },
        { address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5', privKey: 'cUWVirwp5vh1D6WWbYci3tuGniyf28ERpgU4uL5VSiFDfvNEhJqy' }
      ];
      const signed = Transactions.sign({ chain: 'BTC', tx, keys, utxos });
      const expected =
        '0200000001ab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e64010000006b483045022100a3e6e04d311930ec19b11033e77d973ae37181ead6b2db582ec1c21028c469350220602faacf6f6753b271571452e4597205971ab1d790e60080d50c206c8c327f86012102c8f8fa438666cbd287e28fb384b99555e4acce610e8141e887c9c458bba5db5cffffffff0200000000000000000b6a096a07696f6e3a61626340420f00000000001976a91457884dcfe2ab46d3354a42d97333c95e5b80cf0188ac00000000';
      expect(signed).to.eq(expected);
    });

    it('should sign a BTC tx with uncompressed pubkey inputs', () => {
      const uncompPk = new bitcoreLib.PrivateKey({ bn: '86d32c754853c7d5788d101f0aa5c3ea4da69c0f42ffc3f7403aafba23112b0c', network: 'mainnet', compressed: false });
      const uncompAddy = uncompPk.publicKey.toAddress();
      const compPk = new bitcoreLib.PrivateKey('86d32c754853c7d5788d101f0aa5c3ea4da69c0f42ffc3f7403aafba23112b0c');
      const compAddy = compPk.publicKey.toAddress();

      const tx = new bitcoreLib.Transaction();
      const utxos = [{
        mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
        mintIndex: 0,
        value: 1e8,
        address: uncompAddy,
        script: bitcoreLib.Script.fromAddress(uncompAddy)
      }, {
        mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
        mintIndex: 1,
        value: 1e8,
        address: compAddy,
        script: bitcoreLib.Script.fromAddress(compAddy)
      }];
      const bitcoreUtxos = utxos.map(utxo => new bitcoreLib.Transaction.UnspentOutput({ txid: utxo.mintTxid, vout: utxo.mintIndex, satoshis: utxo.value, ...utxo }));
      tx.from(bitcoreUtxos);
      tx.change('mpNpzMoprLnSBu8CWDunNCYeJq3Mzdk59V');
      expect(tx.inputs.every(input => input._scriptBuffer?.length === 0)).to.be.true;

      const keys = [{ privKey: uncompPk, address: uncompAddy.toString() }, { privKey: compPk, address: compAddy.toString() }];
      const signed = Transactions.sign({ chain: 'BTC', tx: tx.uncheckedSerialize(), utxos, keys });
      const signedTx = new bitcoreLib.Transaction(signed);
      expect(signedTx.inputs.every(input => input._scriptBuffer?.length > 0)).to.be.true;
    });

    it.skip('should fail to get signatures on a BTC txs', () => {
      // TODO !!
    });

    it('should be able to create a livenet ETH tx', () => {
      const rawEthTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETH',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf9014f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000018080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a livenet ETH type 1 tx', () => {
      const rawEthTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETH',
        recipients,
        nonce: 0,
        txType: 1
      });
      const expectedTx =
        '0x01f9014e01808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000c0';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a livenet ETH type 2 tx', () => {
      const rawEthTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        maxGasFee: 20000000000
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETH',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0x02f9014f0180018504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000c0';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a testnet ETH tx', () => {
      const rawEthTx = {
        network: 'testnet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETH',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf90152808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead14680563000000000000000000000000000000000000000000000000000000000000000083aa36a78080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a testnet ETH type 2 tx', () => {
      const rawEthTx = {
        network: 'sepolia',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xf9014f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000058080',
        maxGasFee: 20000000000
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETH',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0x02f9018083aa36a780018504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90152f9014f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000058080c0';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a sepolia ETH tx', () => {
      const rawEthTx = {
        network: 'sepolia',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETH',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf90152808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead14680563000000000000000000000000000000000000000000000000000000000000000083aa36a78080';
      expect(cryptoTx).to.equal(expectedTx);
    });
    it('should be able to create a holesky ETH tx', () => {
      const rawEthTx = {
        network: 'holesky',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETH',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf90151808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead1468056300000000000000000000000000000000000000000000000000000000000000008242688080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a livenet ERC20 tx', () => {
      const rawEthTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        gasPrice: 20000000000,
        tokenAddress: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a'
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETHERC20',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf867808504a817c8008094692a70d2e424a56d2c6c27aa97d1a86395877b3a80b844a9059cbb00000000000000000000000037d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a000000000000000000000000000000000000000000000000000dd764300b8000018080';

      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a livenet ERC20 type 2 tx', () => {
      const rawEthTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        maxGasFee: 20000000000,
        tokenAddress: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a'
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETHERC20',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0x02f8670180018504a817c8008094692a70d2e424a56d2c6c27aa97d1a86395877b3a80b844a9059cbb00000000000000000000000037d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a000000000000000000000000000000000000000000000000000dd764300b8000c0';

      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a testnet ERC20 tx', () => {
      const rawEthTx = {
        network: 'testnet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        gasPrice: 20000000000,
        tokenAddress: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a'
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETHERC20',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf86a808504a817c8008094692a70d2e424a56d2c6c27aa97d1a86395877b3a80b844a9059cbb00000000000000000000000037d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a000000000000000000000000000000000000000000000000000dd764300b800083aa36a78080';

      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a testnet ERC20 type 2 tx', () => {
      const rawEthTx = {
        network: 'sepolia',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        maxGasFee: 20000000000,
        tokenAddress: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a'
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETHERC20',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0x02f86a83aa36a780018504a817c8008094692a70d2e424a56d2c6c27aa97d1a86395877b3a80b844a9059cbb00000000000000000000000037d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a000000000000000000000000000000000000000000000000000dd764300b8000c0';

      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a sepolia ERC20 tx', () => {
      const rawEthTx = {
        network: 'sepolia',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        gasPrice: 20000000000,
        tokenAddress: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a'
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETHERC20',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf86a808504a817c8008094692a70d2e424a56d2c6c27aa97d1a86395877b3a80b844a9059cbb00000000000000000000000037d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a000000000000000000000000000000000000000000000000000dd764300b800083aa36a78080';

      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a holesky ERC20 tx', () => {
      const rawEthTx = {
        network: 'holesky',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        gasPrice: 20000000000,
        tokenAddress: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a'
      };
      const { value, to } = rawEthTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawEthTx,
        chain: 'ETHERC20',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf869808504a817c8008094692a70d2e424a56d2c6c27aa97d1a86395877b3a80b844a9059cbb00000000000000000000000037d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a000000000000000000000000000000000000000000000000000dd764300b80008242688080';

      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a livenet MATIC tx', () => {
      const rawMaticTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'MATIC',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf90150808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead14680563000000000000000000000000000000000000000000000000000000000000000081898080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a livenet MATIC tx an amount in scientific notation', () => {
      const rawMaticTx = {
        network: 'livenet',
        value: 4.279756e+21,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'MATIC',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf90152808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a89e8018baee182ae0000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead14680563000000000000000000000000000000000000000000000000000000000000000081898080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a livenet MATIC type 2 tx', () => {
      const rawMaticTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        maxGasFee: 30000000000
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'MATIC',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0x02f901558189808506fc23ac008506fc23ac00809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000c0';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a testnet MATIC tx', () => {
      const rawMaticTx = {
        network: 'testnet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'MATIC',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf90152808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000830138828080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a testnet MATIC type 2 tx', () => {
      const rawMaticTx = {
        network: 'testnet',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        maxGasPrice: 20000000000
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'MATIC',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf9014d8080809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000830138828080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a mumbai MATIC tx', () => {
      const rawMaticTx = {
        network: 'mumbai',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        gasPrice: 20000000000
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'MATIC',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0xf90152808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000830138818080';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to create a mumbai MATIC type 2 tx', () => {
      const rawMaticTx = {
        network: 'mumbai',
        value: 3896000000000000,
        to: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A',
        data:
          '0xb6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        maxGasFee: 30000000000
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'MATIC',
        recipients,
        nonce: 0
      });
      const expectedTx =
        '0x02f9015783013881808506fc23ac008506fc23ac00809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000c0';
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should be able to encode Data in ERC20 tx', () => {
      const recipients = [{ address: '0x37d7B3bBD88EFdE6a93cF74D2F5b0385D3E3B08A', amount: 3896000000000000 }];
      const tokenAddress = '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a';
      const data = Transactions.get({ chain: 'ETHERC20' }).encodeData({ recipients, tokenAddress });
      const expectedData =
        '0xa9059cbb00000000000000000000000037d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a000000000000000000000000000000000000000000000000000dd764300b8000';

      expect(data).to.equal(expectedData);
    });

    it('should be able to send ETH to multiple using multisend contract', () => {
      const wallet = {
        address: '0xb4b9be3062b6dB6eDa78fa4b5EA80595Cfa7E655',
        privateKey: '0x733d4cddb30d33f324def2bb80c6a844f7ba342a60bed06d838afb6b37ab1972',
        index: 0
      };
      const rawEthTx = {
        value: '3896000000000000',
        to: '0xf514e00E20373f6366C9AF966fF5F8be587595E9',
      };
      const rawEthTx2 = {
        value: 20407919369583210,
        to: '0x3428F3Eb7df7D4a16f9e4A5098574Cea2CFBbdc6',
      };
      const recipients = [{ address: rawEthTx.to, amount: rawEthTx.value }, { address: rawEthTx2.to, amount: rawEthTx2.value }];
      const cryptoTx = Transactions.create({
        network: 'testnet',
        chain: 'ETH',
        recipients,
        nonce: 3,
        contractAddress: '0x44dfceb88f24c738d8ae9b7d4bb898cbca06db0e',
        gasPrice: 1000000008,
        gasLimit: 71994
      });
      const expectedTx =
        '0xf9013403843b9aca088301193a9444dfceb88f24c738d8ae9b7d4bb898cbca06db0e8756584930ac7a6ab9010425245b26000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f514e00e20373f6366c9af966ff5f8be587595e90000000000000000000000003428f3eb7df7d4a16f9e4a5098574cea2cfbbdc60000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000dd764300b8000000000000000000000000000000000000000000000000000004880e500a0fa6a83aa36a78080';
      expect(cryptoTx).to.equal(expectedTx);

      const signedTx = Transactions.sign({ chain: 'ETH', tx: cryptoTx, key: { address: wallet.address, privKey: wallet.privateKey } });
      const expectedSignedTx =
        '0xf9017503843b9aca088301193a9444dfceb88f24c738d8ae9b7d4bb898cbca06db0e8756584930ac7a6ab9010425245b26000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f514e00e20373f6366c9af966ff5f8be587595e90000000000000000000000003428f3eb7df7d4a16f9e4a5098574cea2cfbbdc60000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000dd764300b8000000000000000000000000000000000000000000000000000004880e500a0fa6a8401546d71a0f9e7f0a170d7f145899042c938e7f0eb4ecdbdc0a5453b6524fcc2b9aea427b2a01477ff7e9379952b26237bead1e7835eef0e5768673c9da4ca7410cd7b57e8c4';
      expect(expectedSignedTx).to.equal(signedTx);
    });

    it('should be able to send ERC20 to multiple using multisend contract', () => {
      const wallet = {
        address: '0xb4b9be3062b6dB6eDa78fa4b5EA80595Cfa7E655',
        privateKey: '0x733d4cddb30d33f324def2bb80c6a844f7ba342a60bed06d838afb6b37ab1972',
        index: 0
      };
      const rawEthTx = {
        value: '3823',
        to: '0xf514e00E20373f6366C9AF966fF5F8be587595E9'
      };
      const rawEthTx2 = {
        value: '900',
        to: '0x3428F3Eb7df7D4a16f9e4A5098574Cea2CFBbdc6'
      };
      const recipients = [{ address: rawEthTx.to, amount: rawEthTx.value }, { address: rawEthTx2.to, amount: rawEthTx2.value }];
      const cryptoTx = Transactions.create({
        network: 'sepolia',
        chain: 'ETHERC20',
        recipients,
        nonce: 48,
        gasPrice: 1806667388,
        gasLimit: 56209,
        contractAddress: '0x328cab2bd398a6e577d8ab1d0ae0b969fd70969c',
        tokenAddress: '0x75c87615ffc0bb34a24ed4ac62c26a1d8ea75336'
      });
      const expectedTx =
        '0xf9014c30846baf8e7c82db9194328cab2bd398a6e577d8ab1d0ae0b969fd70969c80b90124aee2561300000000000000000000000075c87615ffc0bb34a24ed4ac62c26a1d8ea75336000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f514e00e20373f6366c9af966ff5f8be587595e90000000000000000000000003428f3eb7df7d4a16f9e4a5098574cea2cfbbdc600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000eef000000000000000000000000000000000000000000000000000000000000038483aa36a78080';
      expect(cryptoTx).to.equal(expectedTx);

      const signedTx = Transactions.sign({ chain: 'ETHERC20', tx: cryptoTx, key: { address: wallet.address, privKey: wallet.privateKey } });
      const expectedSignedTx =
        '0xf9018d30846baf8e7c82db9194328cab2bd398a6e577d8ab1d0ae0b969fd70969c80b90124aee2561300000000000000000000000075c87615ffc0bb34a24ed4ac62c26a1d8ea75336000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f514e00e20373f6366c9af966ff5f8be587595e90000000000000000000000003428f3eb7df7d4a16f9e4a5098574cea2cfbbdc600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000eef00000000000000000000000000000000000000000000000000000000000003848401546d71a0fb3b5eb6c629245291d729b2f9150ad4a61fe5f040b4eac84510cb1da7bccf0ca068af98a86fcb1184851bbf51667b37777a4d6049d1ca5cc9521691cda42cc75f';
      expect(expectedSignedTx).to.equal(signedTx);
    });

    it('should be able to send MATIC to multiple using multisend contract', () => {
      const wallet = {
        address: '0xb4b9be3062b6dB6eDa78fa4b5EA80595Cfa7E655',
        privateKey: '0x733d4cddb30d33f324def2bb80c6a844f7ba342a60bed06d838afb6b37ab1972',
        index: 0
      };
      const rawMaticTx = {
        value: BigInt(3896000000000000),
        to: '0xf514e00E20373f6366C9AF966fF5F8be587595E9',
      };
      const rawMaticTx2 = {
        value: 20407919369583210,
        to: '0x3428F3Eb7df7D4a16f9e4A5098574Cea2CFBbdc6',
      };
      const recipients = [{ address: rawMaticTx.to, amount: rawMaticTx.value }, { address: rawMaticTx2.to, amount: rawMaticTx2.value }];
      const cryptoTx = Transactions.create({
        network: 'testnet',
        chain: 'MATIC',
        recipients,
        nonce: 3,
        contractAddress: '0x44dfceb88f24c738d8ae9b7d4bb898cbca06db0e',
        gasPrice: 1000000008,
        gasLimit: 71994
      });
      const expectedTx = '0xf9013403843b9aca088301193a9444dfceb88f24c738d8ae9b7d4bb898cbca06db0e8756584930ac7a6ab9010425245b26000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f514e00e20373f6366c9af966ff5f8be587595e90000000000000000000000003428f3eb7df7d4a16f9e4a5098574cea2cfbbdc60000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000dd764300b8000000000000000000000000000000000000000000000000000004880e500a0fa6a830138828080';
      expect(cryptoTx).to.equal(expectedTx);

      const signedTx = Transactions.sign({ chain: 'MATIC', tx: cryptoTx, key: { address: wallet.address, privKey: wallet.privateKey } });
      const expectedSignedTx =
        '0xf9017403843b9aca088301193a9444dfceb88f24c738d8ae9b7d4bb898cbca06db0e8756584930ac7a6ab9010425245b26000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f514e00e20373f6366c9af966ff5f8be587595e90000000000000000000000003428f3eb7df7d4a16f9e4a5098574cea2cfbbdc60000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000dd764300b8000000000000000000000000000000000000000000000000000004880e500a0fa6a83027127a007e38abe47de10fc653ed198900e219f3d2e1b8ecad05c442fbd4d37ce2dad4fa027506463182caadd2728cba17ffcd3adb67b9043397480d39f1d3a2740692c8f';
      expect(expectedSignedTx).to.equal(signedTx);
    });

    it('should be able to create a XRP tx', () => {
      const recipients = [{ address: 'rEqj9WKSH7wEkPvWf6b4gCi26Y3F7HbKUF', amount: '123456' }];
      const xrpParams = {
        chain: 'XRP',
        recipients,
        from: 'rEqj9WKSH7wEkPvWf6b4gCi26Y3F7HbKUF',
        tag: 123456,
        fee: 12,
        nonce: 1,
        invoiceID: '1012345678901234567890123456710123456789012345678901567890123456'
      };
      const cryptoTx = Transactions.create(xrpParams);
      const expectedTx =
        '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C8114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502';
      expect(xrpParams.invoiceID.length).to.equal(64);
      expect(cryptoTx).to.equal(expectedTx);
    });

    it('should fail to create a XRP tx with invalid invoiceID', () => {
      try {
        const recipients = [{ address: 'rEqj9WKSH7wEkPvWf6b4gCi26Y3F7HbKUF', amount: '123456' }];
        const xrpParams = {
          chain: 'XRP',
          recipients,
          from: 'rEqj9WKSH7wEkPvWf6b4gCi26Y3F7HbKUF',
          tag: 123456,
          fee: 12,
          nonce: 1,
          invoiceID: '78901234567890123456710123456789012345678901567890123456'
        };
        Transactions.create(xrpParams);
      } catch (err) {
        expect(err).to.exist;
        expect(err.message).to.equal('Invalid Hash length 28');
      }
    });

    it('should fail to create a XRP tx with invalid address', () => {
      try {
        const recipients = [{ address: 'rEqj9WKSH7wEkPvWf6b4gCi26Y3F7HbKUF', amount: '123456' }];
        const xrpParams = {
          chain: 'XRP',
          recipients,
          from: 'rEqj9WKSH7wEkPvWf6b4gCF',
          tag: 123456,
          fee: 12,
          nonce: 1,
          invoiceID: '1012345678901234567890123456710123456789012345678901567890123456'
        };
        Transactions.create(xrpParams);
      } catch (err) {
        expect(err).to.exist;
        expect(err.message).to.equal('checksum_invalid');
      }
    });

    it('should create a DOGE tx', () => {
      const recipients = [{ address: 'mpNpzMoprLnSBu8CWDunNCYeJq3Mzdk59V', amount: 1e8 }];
      const change = 'msnAsQcCdtzDyiSWb4ZnNxFwUy3P9ogQvY';
      const utxos = [
        {
          mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
          mintIndex: 1,
          value: 0.02503422 * 1e8,
          script: '76a91457884dcfe2ab46d3354a42d97333c95e5b80cf0188ac',
          address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5',
          sequenceNumber: 4294967294
        },
        {
          mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
          mintIndex: 0,
          value: 1e8,
          script: '76a9144e744a19a009a9dd43a23a7c12045c83e82ac9d288ac',
          address: 'mnfnJx2xWWptYmBzck3rdE851Dtu9GaZ3F',
          sequenceNumber: 4294967294
        }
      ];
      const fee = 7440;
      const tx = Transactions.create({ chain: 'DOGE', recipients, change, utxos, fee, rbf: true });

      const keys = [
        {
          address: 'mnfnJx2xWWptYmBzck3rdE851Dtu9GaZ3F',
          privKey: 'cSFjiifSbZ2hU4jTFwE993LCe2rkZGULCTGWTDWXzHvuXRKxpnc1'
        },
        { address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5', privKey: 'cUWVirwp5vh1D6WWbYci3tuGniyf28ERpgU4uL5VSiFDfvNEhJqy' }
      ];
      const signed = Transactions.sign({ chain: 'DOGE', tx, keys, utxos });
      const expected =
        '0100000002ab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e64010000006b483045022100b4fb37f92fb4ec7007166c415d59d888c9526b4550e3ed111e615cfe0e63ba9a022003381d0c43cf3e0762926f4fdff05a2d16fc0e62d59d79a9ca69646d1595b887012102c8f8fa438666cbd287e28fb384b99555e4acce610e8141e887c9c458bba5db5cffffffffab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e64000000006a47304402207b4a0deed6371e8ad46bcae7a9a098d99f2210d44600bab72bccba747ef7554c02207678fb99e91275c4fc7d5665371fb935cb789b4e0ad5a880780513368cca8b4b01210321f2f13aed42db7257b64f77d574071a6e81e460ab3693eefb7482c12d1ff697ffffffff0200e1f505000000001976a914612fb4d5e27a28f5c54018d8948ca3a650741c4188acee152600000000001976a91486823ef7c8e210184cc8675189d37c4c9d8e1e0288ac00000000';
      expect(signed).to.eq(expected);
    });

    it('should create a LTC tx', () => {
      const recipients = [{ address: 'mpNpzMoprLnSBu8CWDunNCYeJq3Mzdk59V', amount: 1e8 }];
      const change = 'msnAsQcCdtzDyiSWb4ZnNxFwUy3P9ogQvY';
      const utxos = [
        {
          mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
          mintIndex: 1,
          value: 0.02503422 * 1e8,
          script: '76a91457884dcfe2ab46d3354a42d97333c95e5b80cf0188ac',
          address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5',
          sequenceNumber: 4294967294
        },
        {
          mintTxid: '643ec66d6c4cad4cbdb8ed2166b8078975e0af9bb7ff7e30d394f43b0d9f18ab',
          mintIndex: 0,
          value: 1e8,
          script: '76a9144e744a19a009a9dd43a23a7c12045c83e82ac9d288ac',
          address: 'mnfnJx2xWWptYmBzck3rdE851Dtu9GaZ3F',
          sequenceNumber: 4294967294
        }
      ];
      const fee = 7440;
      const tx = Transactions.create({ chain: 'LTC', recipients, change, utxos, fee, rbf: true });

      const keys = [
        {
          address: 'mnfnJx2xWWptYmBzck3rdE851Dtu9GaZ3F',
          privKey: 'cSFjiifSbZ2hU4jTFwE993LCe2rkZGULCTGWTDWXzHvuXRKxpnc1'
        },
        { address: 'moVnNJpHHfssYJEnMTS5xXyGV8RhRQNRz5', privKey: 'cUWVirwp5vh1D6WWbYci3tuGniyf28ERpgU4uL5VSiFDfvNEhJqy' }
      ];
      const signed = Transactions.sign({ chain: 'LTC', tx, keys, utxos });
      const expected =
        '0200000002ab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e64010000006a47304402202eeb967801c0aad4f8241d8f90e2a9e2236f95c189165ba6b2ba4dc6b17bacbe02201b5d4dc0c32f6aa134d93698f85bf4c098d15fcbaada0b6ca2b8076fd8aa2741012102c8f8fa438666cbd287e28fb384b99555e4acce610e8141e887c9c458bba5db5cffffffffab189f0d3bf494d3307effb79bafe0758907b86621edb8bd4cad4c6c6dc63e64000000006a473044022072bdde2c0b413fc42d15d93e768a26f818dc5b225b9359235c09fd0452d6121a022007c00afa396d60d5b7919f2ba31e638817561cab4e2afed7a86dd636ee293c1001210321f2f13aed42db7257b64f77d574071a6e81e460ab3693eefb7482c12d1ff697ffffffff0200e1f505000000001976a914612fb4d5e27a28f5c54018d8948ca3a650741c4188acee152600000000001976a91486823ef7c8e210184cc8675189d37c4c9d8e1e0288ac00000000';
      expect(signed).to.eq(expected);
    });

    it('should be able to create a livenet SOL tx', () => {
      const rawMaticTx = {
        network: 'livenet',
        value: 3896000000000000,
        to: 'F7FknkRckx4yvA3Gexnx1H3nwPxndMxVt58BwAzEQhcY',
        from: '8WyoNvKsmfdG6zrbzNBVN8DETyLra3ond61saU9C52YR',
        category: 'transfer',
        blockHash: 'GtV1Hb3FvP3HURHAsj8mGwEqCumvP3pv3i6CVCzYNj3d',
        blockHeight: 531575,
      };
      const { value, to } = rawMaticTx;
      const recipients = [{ address: to, amount: value }];
      const cryptoTx = Transactions.create({
        ...rawMaticTx,
        chain: 'SOL',
        recipients,
      });
      const expectedTx =
        'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDb6/gH5XxrVl86CZd+DpqA1jN8YSz91e8yXxOlyeS8tLRnckLdZVIkhi0iAExccvYpTw5tIfPZ8z/OJGQtnvg9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7A+XJrI4siFXUreDo+M94DBeuJwm0Oq5kHqeWuAw7xgBAgIAAQwCAAAAAIALMGTXDQA=';
      expect(cryptoTx).to.equal(expectedTx);
    });


  });

  describe('sign', () => {
    it('should sign an ETH tx', () => {
      const signedTx = Transactions.sign({
        chain: 'ETH',
        tx:
          '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        key: {
          privKey: '0x29a1271a8214ccf499b99070115adc43539d4e086b5babab57c4c7a88f959cc2'
        }
      });
      const expectedSignedTx =
        '0xf9018f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead1468056300000000000000000000000000000000000000000000000000000000000000001ba0db427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3da02eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f7';
      expect(signedTx).to.equal(expectedSignedTx);
    });

    it('should sign an MATIC tx', () => {
      const signedTx = Transactions.sign({
        chain: 'MATIC',
        tx:
          '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        key: {
          privKey: '0x29a1271a8214ccf499b99070115adc43539d4e086b5babab57c4c7a88f959cc2'
        }
      });
      const expectedSignedTx =
        '0xf9018f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead1468056300000000000000000000000000000000000000000000000000000000000000001ba0db427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3da02eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f7';
      expect(signedTx).to.equal(expectedSignedTx);
    });

    it('should sign a XRP tx', () => {
      const signedTx = Transactions.sign({
        chain: 'XRP',
        tx:
          '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C8114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502',
        key: {
          privKey: 'D02C6801D8F328FF2EAD51D01F9580AF36C8D74E2BD463963AC4ADBE51AE5F2C',
          pubKey: '03DBEEC5E9E76DA09C5B502A67136BC2D73423E8902A7C35A8CBC0C5A6AC0469E8'
        }
      });
      const expectedSignedTx =
        '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C732103DBEEC5E9E76DA09C5B502A67136BC2D73423E8902A7C35A8CBC0C5A6AC0469E874473045022100D5C19360E77D691A11CA693F6E8D8472DA6749D16A06E072ED1110EB3FD9E2C80220169F95E55943C3575CEAA46413FE660E4F8F2E7158FAC235DC3CB9C9F26918098114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502';
      expect(signedTx).to.equal(expectedSignedTx);
    });

    it('should sign a SOL tx', async () => {
      const signedTx = await Transactions.sign({
        chain: 'SOL',
        tx:
          'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDb6/gH5XxrVl86CZd+DpqA1jN8YSz91e8yXxOlyeS8tLRnckLdZVIkhi0iAExccvYpTw5tIfPZ8z/OJGQtnvg9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7A+XJrI4siFXUreDo+M94DBeuJwm0Oq5kHqeWuAw7xgBAgIAAQwCAAAAAIALMGTXDQA=',
        key: {
          privKey: '2L4P42HQHDGBCvMpbtL1D5SQL5NJXqcz3pWNYSN8rjUP',
          pubKey: '8WyoNvKsmfdG6zrbzNBVN8DETyLra3ond61saU9C52YR'
        }
      });
      const expectedSignedTx =
        'AQe68soLnMZOcMIGS3G8SL2L3Maee5wfkL5dw9ixDXKxD+uPteddRItdR3G3qIkOnfZKQ6LaUufTMQioJblEZAIBAAEDb6/gH5XxrVl86CZd+DpqA1jN8YSz91e8yXxOlyeS8tLRnckLdZVIkhi0iAExccvYpTw5tIfPZ8z/OJGQtnvg9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7A+XJrI4siFXUreDo+M94DBeuJwm0Oq5kHqeWuAw7xgBAgIAAQwCAAAAAIALMGTXDQA=';
      expect(signedTx).to.equal(expectedSignedTx);
    });

    it('should not fail to sign a XRP tx with lowercase key', () => {
      const signedTx = Transactions.sign({
        chain: 'XRP',
        tx:
          '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C8114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502',
        key: {
          privKey: 'd02c6801d8f328ff2ead51d01f9580af36c8d74e2bd463963ac4adbe51ae5f2c',
          pubKey: '03dbeec5e9e76da09c5b502a67136bc2d73423e8902a7c35a8cbc0c5a6ac0469e8'
        }
      });
      const expectedSignedTx =
        '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C732103DBEEC5E9E76DA09C5B502A67136BC2D73423E8902A7C35A8CBC0C5A6AC0469E874473045022100D5C19360E77D691A11CA693F6E8D8472DA6749D16A06E072ED1110EB3FD9E2C80220169F95E55943C3575CEAA46413FE660E4F8F2E7158FAC235DC3CB9C9F26918098114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502';
      expect(signedTx).to.equal(expectedSignedTx);
    });

    it('should throw using wrong privKey to sign an ETH tx', () => {
      let error;
      try {
        Transactions.sign({
          chain: 'ETH',
          tx:
            '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
          key: {
            privKey: 'wrongPrivateKey'
          }
        });
      } catch (err) {
        error = err;
      }
      expect(error.message).to.include('invalid BytesLike value');
      expect(error).to.not.equal(undefined);
    });

    it('should throw using wrong privKey to sign an MATIC tx', () => {
      let error;
      try {
        Transactions.sign({
          chain: 'MATIC',
          tx:
            '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
          key: {
            privKey: 'wrongPrivateKey'
          }
        });
      } catch (err) {
        error = err;
      }
      expect(error.message).to.include('invalid BytesLike value');
      expect(error).to.not.equal(undefined);
    });
  });

  describe('getSignature', function() {
    it('should be able to getSignature an ETH tx', () => {
      const signature = Transactions.getSignature({
        chain: 'ETH',
        tx:
          '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        key: {
          privKey: '0x29a1271a8214ccf499b99070115adc43539d4e086b5babab57c4c7a88f959cc2'
        }
      });
      const expectedSignature =
        '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b';
      expect(signature).to.equal(expectedSignature);
    });

    it('should be able to getSignature an MATIC tx', () => {
      const signature = Transactions.getSignature({
        chain: 'MATIC',
        tx:
          '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        key: {
          privKey: '0x29a1271a8214ccf499b99070115adc43539d4e086b5babab57c4c7a88f959cc2'
        }
      });
      const expectedSignature =
        '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b';
      expect(signature).to.equal(expectedSignature);
    });
  });

  describe('applyTransaction', function() {
    describe('BTC', function() {
      const chain = 'BTC';
      const network = 'regtest';
      const lib = bitcoreLib;
      const privkey = new lib.PrivateKey('65a1c4421a01e07355a59aa4d7d2b2ebd4d14e3c3ce0c239b9081a523c5d69ba', network);
      const pubkey = privkey.toPublicKey();
      const to = 'bcrt1qxerc45n2rv360s8z3wj67fdq93h22m5gstud4z';
      const change = pubkey.toAddress(network, 'p2pkh');

      it('should apply signature to a P2PK tx', function() {
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.buildPublicKeyOut(pubkey).toString()
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2PKH tx', function() {
        const addy = pubkey.toAddress(network, 'p2pkh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2SH tx', function() {
        const addy = pubkey.toAddress(network, 'p2sh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2WPKH tx', function() {
        const addy = pubkey.toAddress(network, 'p2wpkh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a multisig P2SH tx', function() {
        const privkey2 = new lib.PrivateKey('61059599ffc27072ccb7a7ddbe32c031433bf3b7bf1e128b0b4e80a6c68c027e', network);
        const pubkey2 = privkey2.toPublicKey();
        const privkey3 = new lib.PrivateKey('4fac3c5338abc4cd27ef98ad1122215dc4651c4f30c9c59ebe7b33dc416ec33e', network);
        const pubkey3 = privkey3.toPublicKey();
        const addy = lib.Address.createMultisig([pubkey, pubkey2, pubkey3], 2, network, false); // p2sh
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          }, [pubkey, pubkey2, pubkey3], 2)
          .to(to, 1234)
          .change(change);

        const signature2 = tx.inputs[0].getSignatures(tx, privkey2, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed2 = Transactions.applySignature({ chain, tx, signature: signature2, index: 0 });
        expect(signed2).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signature3 = tx.inputs[0].getSignatures(tx, privkey3, 0)[0];
        const signed3 = Transactions.applySignature({ chain, tx, signature: signature3, index: 0 });
        expect(signed3).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a multisig P2WSH tx', function() {
        const privkey2 = new lib.PrivateKey('61059599ffc27072ccb7a7ddbe32c031433bf3b7bf1e128b0b4e80a6c68c027e', network);
        const pubkey2 = privkey2.toPublicKey();
        const privkey3 = new lib.PrivateKey('4fac3c5338abc4cd27ef98ad1122215dc4651c4f30c9c59ebe7b33dc416ec33e', network);
        const pubkey3 = privkey3.toPublicKey();
        const addy = lib.Address.createMultisig([pubkey, pubkey2, pubkey3], 2, network, true); // p2wsh
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          }, [pubkey, pubkey2, pubkey3], 2)
          .to(to, 1234)
          .change(change);

        const signature2 = tx.inputs[0].getSignatures(tx, privkey2, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed2 = Transactions.applySignature({ chain, tx, signature: signature2, index: 0 });
        expect(signed2).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signature3 = tx.inputs[0].getSignatures(tx, privkey3, 0)[0];
        const signed3 = Transactions.applySignature({ chain, tx, signature: signature3, index: 0 });
        expect(signed3).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2TR tx', function() {
        const addy = pubkey.toAddress(network, 'p2tr');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });
    });

    describe('BCH', function() {
      const chain = 'BCH';
      const network = 'regtest';
      const lib = bitcoreLibCash;
      const privkey = new lib.PrivateKey('65a1c4421a01e07355a59aa4d7d2b2ebd4d14e3c3ce0c239b9081a523c5d69ba', network);
      const pubkey = privkey.toPublicKey();
      const to = 'qzpjx6cvau7tunx0hxvr4czrrllm0ecd95gz8y5euh';
      const change = pubkey.toAddress(network, 'p2pkh');

      it('should apply signature to a P2PK tx', function() {
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.buildPublicKeyOut(pubkey).toString()
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2PKH tx', function() {
        const addy = pubkey.toAddress(network, 'p2pkh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it.skip('should apply signature to a P2SH tx', function() {
        // single-sig P2SH is not completely supported in bitcore-lib-cash due to it's unusual usage, unlike BTC and LTC
        // skipping this test for now but leaving it as a possibility if/when we add full P2SH support in bitcore-lib-cash
        const addy = pubkey.toAddress(network, 'p2sh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1234)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a multisig P2SH tx', function() {
        const privkey2 = new lib.PrivateKey('61059599ffc27072ccb7a7ddbe32c031433bf3b7bf1e128b0b4e80a6c68c027e', network);
        const pubkey2 = privkey2.toPublicKey();
        const privkey3 = new lib.PrivateKey('4fac3c5338abc4cd27ef98ad1122215dc4651c4f30c9c59ebe7b33dc416ec33e', network);
        const pubkey3 = privkey3.toPublicKey();
        const addy = lib.Address.createMultisig([pubkey, pubkey2, pubkey3], 2, network, false); // p2sh
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          }, [pubkey, pubkey2, pubkey3], 2)
          .to(to, 1234)
          .change(change);

        const signature2 = tx.inputs[0].getSignatures(tx, privkey2, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed2 = Transactions.applySignature({ chain, tx, signature: signature2, index: 0 });
        expect(signed2).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signature3 = tx.inputs[0].getSignatures(tx, privkey3, 0)[0];
        const signed3 = Transactions.applySignature({ chain, tx, signature: signature3, index: 0 });
        expect(signed3).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to an escrow tx', function() {
        const privkey2 = new lib.PrivateKey('61059599ffc27072ccb7a7ddbe32c031433bf3b7bf1e128b0b4e80a6c68c027e', network);
        const pubkey2 = privkey2.toPublicKey();
        const privkey3 = new lib.PrivateKey('4fac3c5338abc4cd27ef98ad1122215dc4651c4f30c9c59ebe7b33dc416ec33e', network);
        const pubkey3 = privkey3.toPublicKey();
        const addy = lib.Address.createMultisig([pubkey, pubkey2, pubkey3], 2, network, false); // p2sh
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          }, [pubkey, pubkey2, pubkey3], 2)
          .to(to, 1234)
          .change(change);

        const signature2 = tx.inputs[0].getSignatures(tx, privkey2, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed2 = Transactions.applySignature({ chain, tx, signature: signature2, index: 0 });
        expect(signed2).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signature3 = tx.inputs[0].getSignatures(tx, privkey3, 0)[0];
        const signed3 = Transactions.applySignature({ chain, tx, signature: signature3, index: 0 });
        expect(signed3).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });
    });

    describe('DOGE', function() {
      const chain = 'DOGE';
      const network = 'regtest';
      const lib = bitcoreLibDoge;
      const privkey = new lib.PrivateKey('65a1c4421a01e07355a59aa4d7d2b2ebd4d14e3c3ce0c239b9081a523c5d69ba', network);
      const pubkey = privkey.toPublicKey();
      const to = 'mwHPw7Vtty66L9znjDY2NhFB2wJG7Lw42v';
      const change = pubkey.toAddress(network, 'p2pkh');

      it('should apply signature to a P2PK tx', function() {
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.buildPublicKeyOut(pubkey).toString()
          })
          .to(to, 1e7)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2PKH tx', function() {
        const addy = pubkey.toAddress(network, 'p2pkh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1e7)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it.skip('should apply signature to a P2SH tx', function() {
        // single-sig P2SH is not completely supported in bitcore-lib-doge due to it's unusual usage, unlike BTC and LTC
        // skipping this test for now but leaving it as a possibility if/when we add full P2SH support in bitcore-lib-doge
        const addy = pubkey.toAddress(network, 'p2sh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1e7)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a multisig P2SH tx', function() {
        const privkey2 = new lib.PrivateKey('61059599ffc27072ccb7a7ddbe32c031433bf3b7bf1e128b0b4e80a6c68c027e', network);
        const pubkey2 = privkey2.toPublicKey();
        const privkey3 = new lib.PrivateKey('4fac3c5338abc4cd27ef98ad1122215dc4651c4f30c9c59ebe7b33dc416ec33e', network);
        const pubkey3 = privkey3.toPublicKey();
        const addy = lib.Address.createMultisig([pubkey, pubkey2, pubkey3], 2, network, false); // p2sh
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          }, [pubkey, pubkey2, pubkey3], 2)
          .to(to, 1e7)
          .change(change);

        const signature2 = tx.inputs[0].getSignatures(tx, privkey2, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed2 = Transactions.applySignature({ chain, tx, signature: signature2, index: 0 });
        expect(signed2).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signature3 = tx.inputs[0].getSignatures(tx, privkey3, 0)[0];
        const signed3 = Transactions.applySignature({ chain, tx, signature: signature3, index: 0 });
        expect(signed3).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });
    });

    describe('LTC', function() {
      const chain = 'LTC';
      const network = 'regtest';
      const lib = bitcoreLibLtc;
      const privkey = new lib.PrivateKey('65a1c4421a01e07355a59aa4d7d2b2ebd4d14e3c3ce0c239b9081a523c5d69ba', network);
      const pubkey = privkey.toPublicKey();
      const to = 'rltc1q6tvvdn702mmfnu0ujdkw97qw9aac9xm2c6wgk6';
      const change = pubkey.toAddress(network, 'p2pkh');

      it('should apply signature to a P2PK tx', function() {
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.buildPublicKeyOut(pubkey).toString()
          })
          .to(to, 1e4)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2PKH tx', function() {
        const addy = pubkey.toAddress(network, 'p2pkh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1e4)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2SH tx', function() {
        const addy = pubkey.toAddress(network, 'p2sh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1e4)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a P2WPKH tx', function() {
        const addy = pubkey.toAddress(network, 'p2wpkh');
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy)
          })
          .to(to, 1e4)
          .change(change);

        const signature = tx.inputs[0].getSignatures(tx, privkey, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed = Transactions.applySignature({ chain, tx, signature, index: 0 });
        expect(signed).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a multisig P2SH tx', function() {
        const privkey2 = new lib.PrivateKey('61059599ffc27072ccb7a7ddbe32c031433bf3b7bf1e128b0b4e80a6c68c027e', network);
        const pubkey2 = privkey2.toPublicKey();
        const privkey3 = new lib.PrivateKey('4fac3c5338abc4cd27ef98ad1122215dc4651c4f30c9c59ebe7b33dc416ec33e', network);
        const pubkey3 = privkey3.toPublicKey();
        const addy = lib.Address.createMultisig([pubkey, pubkey2, pubkey3], 2, network, false); // p2sh
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          }, [pubkey, pubkey2, pubkey3], 2)
          .to(to, 1e4)
          .change(change);

        const signature2 = tx.inputs[0].getSignatures(tx, privkey2, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed2 = Transactions.applySignature({ chain, tx, signature: signature2, index: 0 });
        expect(signed2).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signature3 = tx.inputs[0].getSignatures(tx, privkey3, 0)[0];
        const signed3 = Transactions.applySignature({ chain, tx, signature: signature3, index: 0 });
        expect(signed3).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });

      it('should apply signature to a multisig P2WSH tx', function() {
        const privkey2 = new lib.PrivateKey('61059599ffc27072ccb7a7ddbe32c031433bf3b7bf1e128b0b4e80a6c68c027e', network);
        const pubkey2 = privkey2.toPublicKey();
        const privkey3 = new lib.PrivateKey('4fac3c5338abc4cd27ef98ad1122215dc4651c4f30c9c59ebe7b33dc416ec33e', network);
        const pubkey3 = privkey3.toPublicKey();
        const addy = lib.Address.createMultisig([pubkey, pubkey2, pubkey3], 2, network, true); // p2wsh
        const tx = new lib.Transaction()
          .from({
            txid: 'ba50b12d89162134c31a89ae1f289a1c86fe0a2e7c1861768296408090e30864',
            vout: 0,
            satoshis: 1e9,
            script: lib.Script.fromAddress(addy).toString()
          }, [pubkey, pubkey2, pubkey3], 2)
          .to(to, 1e4)
          .change(change);

        const signature2 = tx.inputs[0].getSignatures(tx, privkey2, 0)[0];
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signed2 = Transactions.applySignature({ chain, tx, signature: signature2, index: 0 });
        expect(signed2).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(false);
        const signature3 = tx.inputs[0].getSignatures(tx, privkey3, 0)[0];
        const signed3 = Transactions.applySignature({ chain, tx, signature: signature3, index: 0 });
        expect(signed3).to.equal(tx);
        expect(tx.inputs[0].isFullySigned()).to.equal(true);
        expect(() => tx.serialize()).to.not.throw();
      });
    });


    it('should apply signatures to an ETH tx', () => {
      const signedTx = Transactions.applySignature({
        chain: 'ETH',
        tx:
          '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        signature:
          '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b'
      });

      const expectedSignedTx =
        '0xf9018f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead1468056300000000000000000000000000000000000000000000000000000000000000001ba0db427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3da02eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f7';
      expect(signedTx).to.equal(expectedSignedTx);
    });

    it('should apply signatures to an ETH tx type 2', () => {
      const expectedTx =
        '0x02f9017d0580808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90152f9014f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000058080c0';
      const parsedTx = ethers.Transaction.from(expectedTx);
      expect(parsedTx.type).to.equal(2);
      expect(parsedTx.maxFeePerGas).to.not.equal(null);
      expect(parsedTx.gasPrice).to.equal(null);

      const signedTx = Transactions.applySignature({
        chain: 'ETH',
        tx: expectedTx,
        signature:
          '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b'
      });

      const expectedSignedTx =
        '0x02f901c00580808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90152f9014f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000058080c080a0db427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3da02eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f7';
      const parsedSignedTx = ethers.Transaction.from(expectedSignedTx);
      expect(signedTx).to.equal(expectedSignedTx);
      expect(parsedSignedTx.type).to.equal(2);
      expect(parsedSignedTx.maxFeePerGas).to.not.equal(null);
      expect(parsedSignedTx.gasPrice).to.equal(null);
    });

    it('should fail to apply signatures to an ETH tx type 2 with insufficient gasPrice or maxGasFee', () => {
      const expectedTx =
        '0xf866018082520894423163e58aabec5daa3dd1130b759d24bef0f6ea8711c37937e080008025a06852e54c99c14b47d64a5c2791d76f2b9694f6b2d925f881793bec474315897ea0116f3a4ac81642aaac3bcb33fefb46fab24608dfdfaba5cc56e8c0e6022b020a';
      const parsedTx = ethers.Transaction.from(expectedTx);
      expect(!!parsedTx.maxFeePerGas).to.equal(false);
      expect(!!parsedTx.gasPrice).to.equal(false);
      let error;
      try {
        const signedTx = Transactions.applySignature({
          chain: 'ETH',
          tx: expectedTx,
          signature:
            '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b'
        });
      } catch (err) {
        error = err;
      }
      expect(error).to.not.equal(undefined);
      expect(error.message).to.include('either gasPrice or maxFeePerGas is required');
    });

    it('should fail to apply signatures to an ETH tx if signature is invalid', () => {
      expect(() => {
        Transactions.applySignature({
          chain: 'ETH',
          tx:
            '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
          signature: '0xdb'
        });
      }).to.throw('invalid signature');
    });

    it('should apply signatures to an MATIC tx', () => {
      const signedTx = Transactions.applySignature({
        chain: 'MATIC',
        tx:
          '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
        signature:
          '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b'
      });

      const expectedSignedTx =
        '0xf9018f808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead1468056300000000000000000000000000000000000000000000000000000000000000001ba0db427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3da02eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f7';
      expect(signedTx).to.equal(expectedSignedTx);
    });

    it('should apply signatures to an MATIC tx type 2', () => {
      const expectedTx =
        '0x02f901528301388180808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000c0';
      const parsedTx = ethers.Transaction.from(expectedTx);
      expect(parsedTx.type).to.equal(2);
      expect(parsedTx.maxFeePerGas).to.not.equal(null);
      expect(parsedTx.gasPrice).to.equal(null);

      const signedTx = Transactions.applySignature({
        chain: 'MATIC',
        tx: expectedTx,
        signature:
          '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b'
      });

      const expectedSignedTx =
        '0x02f901958301388180808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000c080a0db427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3da02eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f7';
      const parsedSignedTx = ethers.Transaction.from(expectedSignedTx);
      expect(signedTx).to.equal(expectedSignedTx);
      expect(parsedSignedTx.type).to.equal(2);
      expect(parsedSignedTx.maxFeePerGas).to.not.equal(null);
      expect(parsedSignedTx.gasPrice).to.equal(null);
    });

    it('should fail to apply signatures to an MATIC tx type 2 with insufficient gasPrice or maxGasFee', () => {
      const expectedTx =
        '0xf867018082520894423163e58aabec5daa3dd1130b759d24bef0f6ea8711c37937e08000808194a00da3147299808e98b962c45ff89415c8e53cbc1572dc4f275ac4e090c4b5f7b7a02bf658e82ebf130889be5150658c9d13667e0ef9ead5710b8ee21a72490d0186';
      const parsedTx = ethers.Transaction.from(expectedTx);
      expect(!!parsedTx.maxFeePerGas).to.equal(false);
      expect(!!parsedTx.gasPrice).to.equal(false);
      let error;
      try {
        const signedTx = Transactions.applySignature({
          chain: 'MATIC',
          tx: expectedTx,
          signature:
            '0xdb427c4dddcfc816581d657d9f30f8287bdebd9b9cbabc7a535fc67cde9f2b3d2eafc2d79ef47fe045c47f08af54736caf797c27f2e25266d6320243104834f71b'
        });
      } catch (err) {
        error = err;
      }
      expect(error).to.not.equal(undefined);
      expect(error.message).to.include('either gasPrice or maxFeePerGas is required');
    });

    it('should fail to apply signatures to an MATIC tx if signature is invalid', () => {
      expect(() => {
        Transactions.applySignature({
          chain: 'MATIC',
          tx:
            '0xf9014c808504a817c800809437d7b3bbd88efde6a93cf74d2f5b0385d3e3b08a870dd764300b8000b90124b6b4af05000000000000000000000000000000000000000000000000000dd764300b800000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000016ada606a26050bb49a5a8228599e0dd48c1368abd36f4f14d2b74a015b2d168dbcab0773ce399393220df874bb22ca961f351e038acd2ba5cc8c764385c9f23707622cc435000000000000000000000000000000000000000000000000000000000000001c7e247d684a635813267b10a63f7f3ba88b28ca2790c909110b28236cf1b9bba03451e83d5834189f28d4c77802fc76b7c760a42bc8bebf8dd15e6ead146805630000000000000000000000000000000000000000000000000000000000000000',
          signature: '0xdb'
        });
      }).to.throw('invalid signature');
    });

    it('should apply a signature to a SOL tx', () => {
      const signedTx = Transactions.applySignature({
        chain: 'SOL',
        tx: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDb6/gH5XxrVl86CZd+DpqA1jN8YSz91e8yXxOlyeS8tLRnckLdZVIkhi0iAExccvYpTw5tIfPZ8z/OJGQtnvg9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7A+XJrI4siFXUreDo+M94DBeuJwm0Oq5kHqeWuAw7xgBAgIAAQwCAAAAAIALMGTXDQA=',
        signature:
          '6Gpk3UnfTPqUYZWXKR7T6bd5uiPLa4VE6SWFDsVc6QQVeb3F49AEtwjcwUdgpkFyaBQxDonBsA2o95JkjWx7pJ2D'
      });

      const expectedSignedTx =
        'AQEHuvLKC5zGTnDCBktxvEi9i9zGnnucH5C+XcPYsQ1ysQ/rj7XnXUSLXUdxt6iJDp32SkOi2lLn0zEIqCW5RGQBAAEDb6/gH5XxrVl86CZd+DpqA1jN8YSz91e8yXxOlyeS8tLRnckLdZVIkhi0iAExccvYpTw5tIfPZ8z/OJGQtnvg9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7A+XJrI4siFXUreDo+M94DBeuJwm0Oq5kHqeWuAw7xgBAgIAAQwCAAAAAIALMGTXDQA=';
      expect(signedTx).to.equal(expectedSignedTx);
    });

  });

  describe('getHash', function() {
    it('should get ETH tx hash', () => {
      // from https://ethereum.stackexchange.com/questions/31285/how-to-get-raw-ethereum-transaction-hash
      const hash = Transactions.getHash({
        chain: 'ETH',
        tx:
          '0xf86c258502540be40083035b609482e041e84074fc5f5947d4d27e3c44f824b7a1a187b1a2bc2ec500008078a04a7db627266fa9a4116e3f6b33f5d245db40983234eb356261f36808909d2848a0166fa098a2ce3bda87af6000ed0083e3bf7cc31c6686b670bd85cbc6da2d6e85'
      });
      const expectedHash = '0x58e5a0fc7fbc849eddc100d44e86276168a8c7baaa5604e44ba6f5eb8ba1b7eb';
      expect(hash).to.equal(expectedHash);
    });

    it('should get MATIC tx hash', () => {
      // from https://ethereum.stackexchange.com/questions/31285/how-to-get-raw-ethereum-transaction-hash
      const hash = Transactions.getHash({
        chain: 'MATIC',
        tx:
          '0xf86c258502540be40083035b609482e041e84074fc5f5947d4d27e3c44f824b7a1a187b1a2bc2ec500008078a04a7db627266fa9a4116e3f6b33f5d245db40983234eb356261f36808909d2848a0166fa098a2ce3bda87af6000ed0083e3bf7cc31c6686b670bd85cbc6da2d6e85'
      });
      const expectedHash = '0x58e5a0fc7fbc849eddc100d44e86276168a8c7baaa5604e44ba6f5eb8ba1b7eb';
      expect(hash).to.equal(expectedHash);
    });

    it('should get XRP signed tx hash', () => {
      const hash = Transactions.getHash({
        chain: 'XRP',
        tx:
          '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C732103DBEEC5E9E76DA09C5B502A67136BC2D73423E8902A7C35A8CBC0C5A6AC0469E874473045022100D5C19360E77D691A11CA693F6E8D8472DA6749D16A06E072ED1110EB3FD9E2C80220169F95E55943C3575CEAA46413FE660E4F8F2E7158FAC235DC3CB9C9F26918098114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502'
      });
      const expectedHash = '61EA6DF3BD1E435283BA0B06311C7BA683A32A80E465196D9F16A23A439EF6F4';
      expect(hash.length).to.equal(64);
      expect(hash).to.equal(expectedHash);
    });

    it('should get XRP testnet signed tx hash', () => {
      const hash = Transactions.getHash({
        chain: 'XRP',
        network: 'testnet',
        tx:
          '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C732103DBEEC5E9E76DA09C5B502A67136BC2D73423E8902A7C35A8CBC0C5A6AC0469E874473045022100D5C19360E77D691A11CA693F6E8D8472DA6749D16A06E072ED1110EB3FD9E2C80220169F95E55943C3575CEAA46413FE660E4F8F2E7158FAC235DC3CB9C9F26918098114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502'
      });
      const expectedHash = '61EA6DF3BD1E435283BA0B06311C7BA683A32A80E465196D9F16A23A439EF6F4';
      expect(hash.length).to.equal(64);
      expect(hash).to.equal(expectedHash);
    });

    it('should get XRP livenet signed tx hash', () => {
      const hash = Transactions.getHash({
        chain: 'XRP',
        network: 'livenet',
        tx:
          '120000228000000024000000012E0001E2405011101234567890123456789012345671012345678901234567890156789012345661400000000001E24068400000000000000C732103DBEEC5E9E76DA09C5B502A67136BC2D73423E8902A7C35A8CBC0C5A6AC0469E874473045022100D5C19360E77D691A11CA693F6E8D8472DA6749D16A06E072ED1110EB3FD9E2C80220169F95E55943C3575CEAA46413FE660E4F8F2E7158FAC235DC3CB9C9F26918098114A2C8E8CD9A9133CAD90F2668159AAF572612A5028314A2C8E8CD9A9133CAD90F2668159AAF572612A502'
      });
      const expectedHash = '61EA6DF3BD1E435283BA0B06311C7BA683A32A80E465196D9F16A23A439EF6F4';
      expect(hash.length).to.equal(64);
      expect(hash).to.equal(expectedHash);
    });
  });


  describe('ETH getChainId', () => {
    it('should get the correct chainId per network', () => {
      const mainnetId = Transactions.get({ chain: 'ETH' }).getChainId('mainnet');
      expect(mainnetId).to.equal(1);

      const livenetId = Transactions.get({ chain: 'ETH' }).getChainId('livenet');
      expect(livenetId).to.equal(1);

      const testId = Transactions.get({ chain: 'ETH' }).getChainId('testnet');
      expect(testId).to.equal(11155111);

      const sepoliaId = Transactions.get({ chain: 'ETH' }).getChainId('sepolia');
      expect(sepoliaId).to.equal(11155111);

      const holeskyId = Transactions.get({ chain: 'ETH' }).getChainId('holesky');
      expect(holeskyId).to.equal(17000);

      const regtestId = Transactions.get({ chain: 'ETH' }).getChainId('regtest');
      expect(regtestId).to.equal(1337);
    });
  });

  describe('MATIC getChainId', () => {
    it('should get the correct chainId per network', () => {
      const mainnetId = Transactions.get({ chain: 'MATIC' }).getChainId('mainnet');
      expect(mainnetId).to.equal(137);

      const livenetId = Transactions.get({ chain: 'MATIC' }).getChainId('livenet');
      expect(livenetId).to.equal(137);

      const testnetId = Transactions.get({ chain: 'MATIC' }).getChainId('testnet');
      expect(testnetId).to.equal(80002);

      const testId = Transactions.get({ chain: 'MATIC' }).getChainId('mumbai');
      expect(testId).to.equal(80001);

      const amoyId = Transactions.get({ chain: 'MATIC' }).getChainId('amoy');
      expect(amoyId).to.equal(80002);

      const regtestId = Transactions.get({ chain: 'MATIC' }).getChainId('regtest');
      expect(regtestId).to.equal(13375);
    });
  });
});